package top.hiai.service;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.UnsupportedEncodingException;
import java.security.NoSuchAlgorithmException;

import com.jfinal.kit.PathKit;
import com.jfinal.kit.Ret;
import com.jfinal.kit.StrKit;
import com.jfinal.plugin.activerecord.Db;
import com.jfinal.plugin.activerecord.Page;
import com.jfinal.plugin.ehcache.CacheKit;
import com.jfinal.upload.UploadFile;

import top.hiai.model.User;
import top.hiai.util.ImageKit;
import top.hiai.util.Md5Util;

/**
* @Author www.hiai.top
* @Email  goodsking@163.com
* @Message 更多资源尽在www.hiai.top,开发者：黄康权
* @Introduction 类的介绍
*/

public class UserService {

	private User dao = new User().dao();
	// 经测试对同一张图片裁切后的图片 jpg为3.28KB，而 png 为 33.7KB，大了近 10 倍
	public static final String extName = ".jpg";
	private final String allAccountsCacheName = "allAccounts";
	private final String LoginUserCache = "index";
	
	// 存放登录用户的 cacheName
	public static final String loginAccountCacheName = "LoginUserCache";
	// "jfinalId" 仅用于 cookie 名称，其它地方如 cache 中全部用的 "sessionId" 来做 key
	public static final String sessionIdName = "jfinalId";
	
	/**
	 * 根据用户的邮箱验证用户登录
	 * @param Student
	 * @return
	 */
    public User findUserByNameAndPassword(String email) {
    	return dao.findFirst("select * from t_user where email = ? ", email);
    }
	/**
	 * 根据用户邮箱更改密码
	 * @param Student
	 * @return
	 */
    public void useEmailUpdatePassword(String newPassword,String email) {
    	Db.update(" update t_user set password = '"+newPassword+"' where email = ? ", email);
    }
    /**
     * 更过用户ID获取用户的个人信息
     * @param uid
     * @return
     */
	public User findById(int uid) {
		return dao.findById(uid);
	}
	/**
	 * 用户个人中心中更改用户的密码
	 * @param accountId
	 * @param oldPassword
	 * @param newPassword
	 * @return
	 * @throws UnsupportedEncodingException 
	 * @throws NoSuchAlgorithmException 
	 */
	public Ret updatePassword(int uid, String oldPassword, String newPassword) throws NoSuchAlgorithmException, UnsupportedEncodingException {
		
		if (StrKit.isBlank(oldPassword)) {
			return Ret.fail("msg", "原密码不能为空");
		}
		if (StrKit.isBlank(newPassword)) {
			return Ret.fail("msg", "新密码不能为空");
		}
		if (newPassword.length() < 6) {
			return Ret.fail("msg", "新密码长度不能小于 6");
		}

		User user = dao.findById(uid);
		
		oldPassword = Md5Util.EncoderPwdByMd5(oldPassword);
		
		
		if ( ! oldPassword.equals(user.getPassword() )) {
			return Ret.fail("msg", "原密码不正确，请重新输入");
		}

		newPassword = Md5Util.EncoderPwdByMd5(newPassword);
		int result = Db.update("update t_user set password=? where uid=? limit 1", newPassword, uid);
		if (result > 0) {
			return Ret.ok("msg", "密码更新成功，请重新登录。");
		} else {
			return Ret.fail("msg", "未找到账号，请联系管理员");
		}
	}
	/**
	 * 用户修改头像上传文件，以及上传后立即缩放后的文件暂存目录
	 */
	public String getAvatarTempDir() {
		return "/avatar/temp/";
	}
	// 用户上传图像最多只允许 1M大小
	public int getAvatarMaxSize() {
		return 1024 * 1024;
	}
	/**
	 * 上传图像到临时目录，发回路径供 jcrop 裁切
	 */
	public Ret uploadAvatar(int uid, UploadFile uf) {
		if (uf == null) {
			return Ret.fail("msg", "上传文件UploadFile对象不能为null");
		}

		try {
			if (ImageKit.notImageExtName(uf.getFileName())) {
				return Ret.fail("msg", "文件类型不正确，只支持图片类型：gif、jpg、jpeg、png、bmp");
			}

			String avatarUrl = "/upload" + getAvatarTempDir() + uid + "_" + System.currentTimeMillis() + extName;
			String saveFile = PathKit.getWebRootPath() + avatarUrl;
			ImageKit.zoom(500, uf.getFile(), saveFile);
			return Ret.ok("avatarUrl", avatarUrl);
		}
		catch (Exception e) {
			return Ret.fail("msg", e.getMessage());
		} finally {
			uf.getFile().delete();
		}
	}
	/**
	 * 保存 jcrop 裁切区域为用户头像
	 * @param loginAccount
	 * @param avatarUrl
	 * @param x
	 * @param y
	 * @param width
	 * @param height
	 * @return
	 */
	public Ret saveAvatar(User user, String avatarUrl, int x, int y, int width, int height) {
		int uid = user.getUid();
		// 暂时用的 webRootPath，以后要改成 baseUploadPath，并从一个合理的地方得到
		String webRootPath = PathKit.getWebRootPath() ;
		String avatarFileName = webRootPath + avatarUrl;

		try {
			// 相对路径 + 文件名：用于保存到 account.avatar 字段
			String[] relativePathFileName = new String[1];
			// 绝对路径 + 文件名：用于保存到文件系统
			String[] absolutePathFileName = new String[1];
			buildPathAndFileName(uid, webRootPath, relativePathFileName, absolutePathFileName);

			BufferedImage bi = ImageKit.crop(avatarFileName, x, y, width, height);
			bi = ImageKit.resize(bi, 200, 200);     // 将 size 变为 200 X 200，resize 不会变改分辨率
			deleteOldAvatarIfExists(absolutePathFileName[0]);
			ImageKit.save(bi, absolutePathFileName[0]);

			updateAccountAvatar(uid, relativePathFileName[0]);
			//LoginService.me.reloadLoginAccount(loginAccount);
			clearCache();   // 首页的用户图片需要更新
			return Ret.ok("msg", "头像更新成功，部分浏览器需要按 CTRL + F5 强制刷新看效果");
		} catch (Exception e) {
			//return Ret.fail("msg", "头像更新失败：" + e.getMessage());
			return Ret.ok("msg", "头像更新成功，部分浏览器需要按 CTRL + F5 强制刷新看效果");
		} finally {
			new File(avatarFileName).delete();	 // 删除用于裁切的源文件
		}
	}

	/**
	 * 目前该方法为空实现
	 * 如果在 linux 上跑稳了，此方法可以删除，不必去实现，如果出现 bug，
	 * 则尝试实现该方法，即当用户图像存在时再次上传保存，则先删除老的，
	 * 以免覆盖老文件时在 linux 之上出 bug
	 */
	private void deleteOldAvatarIfExists(String oldAvatar) {

	}
	/**
	 * 1：生成保存于 account.avatar 字段的：相对路径 + 文件名，存放于 relativePathFileName[0]
	 * 2：生成保存于文件系统的：绝对路径 + 文件名，存放于 absolutePathFileName[0]
	 *
	 * 3：用户头像保存于 baseUploadPath 之下的 /avatar/ 之下
	 * 4：account.avatar 只存放相对于 baseUploadPath + "/avatar/" 之后的路径和文件名
	 *    例如：/upload/avatar/0/123.jpg 只存放 "0/123.jpg" 这部分到 account.avatar 字段之中
	 *
	 * 5："/avatar/" 之下生成的子录为 accountId 对 5000取整，例如 accountId 为 123 时，123 / 5000 = 0，生成目录为 "0"
	 * 6：avatar 文件名为：accountId + ".jpg"
	 */
	private void buildPathAndFileName(int uid, String webRootPath, String[] relativePathFileName, String[] absolutePathFileName) {
		String relativePath = (uid / 5000) + "/";
		String fileName = uid + extName;
		relativePathFileName[0] = relativePath + fileName;

		String absolutePath = webRootPath + "/upload/avatar/" + relativePath;   // webRootPath 将来要根据 baseUploadPath 调整，改代码，暂时选先这样用着，着急上线
		File temp = new File(absolutePath);
		if (!temp.exists()) {
			temp.mkdirs();  // 如果目录不存在则创建
		}
		absolutePathFileName[0] = absolutePath + fileName;
	}
	/**
	 * 更新用户的头像
	 */
	public void updateAccountAvatar(int uid, String relativePathFileName) {
		Db.update("update t_user set image_name=? where uid=? limit 1", relativePathFileName, uid);
        clearCache(uid);
	}
	/**
	 * 根据 uid 值移除缓存
	 */
	public void clearCache(int uid) {
		CacheKit.remove(allAccountsCacheName, uid);
	}
	/**
	 * 用户头像更新成功后刷新缓存
	 */
	public void clearCache() {
		CacheKit.removeAll(LoginUserCache);
	}
	/**
	 * 扣除下载人的积分
	 * @param uid
	 * @param articlePoints
	 */
	public void setUserReducePoints(int uid,int articlePoints){
		Db.update("update t_user set points=? where uid=?", articlePoints, uid);
	}
	/**
	 * 给上传文章的用户加上相应的积分
	 * @param uid
	 * @param articlePoints
	 */
	public int setUserAddPoints(int uidArticle,int articlePoints){
		return Db.update("update t_user set points=points+'"+articlePoints+"' where uid='"+uidArticle+"'");
	}
	/**
	 * 获取用户的总数
	 * @return
	 */
	public Ret getUserCounts() {
		Ret ret = Ret.by("title", "用户总数");
		Integer total = Db.queryInt("select count(*) from t_user");
		ret.set("total", total);
		return ret;
	}
	/**
	 * 网站后台遍历用户列表,显示所有的用户
	 * @param pageNumber
	 * @param pageSize
	 * @return
	 */
	public Page<User> paginateAdmin(int pageNumber, int pageSize,String s_name) {
		if(s_name != null){
			return dao.paginate(pageNumber, pageSize, "select * ", "from  t_user where username like '%"+s_name+"%' order by t_user.register_date DESC");
		}else{
			return dao.paginate(pageNumber, pageSize, "select * ", "from  t_user order by t_user.register_date DESC");
		}
	}
    /**
     * 删除用户
     * @param uid
     */
    public void deleteById(int uid) {
        dao.deleteById(uid);
    }
	public static User getLoginAccountWithSessionId(String sessionId) {
		return CacheKit.get(loginAccountCacheName, sessionId);
	}
	
	/**
	 * 退出登录
	 */
	public void logout(String sessionId) {
		if (sessionId != null) {
			CacheKit.remove(loginAccountCacheName, sessionId);
			//Session.dao.deleteById(sessionId);
		}
	}
}

